﻿using System;
using System.IO;
using System.Runtime.Serialization;
using System.Runtime.Serialization.Formatters.Binary;  
using System.Collections.Generic;
using System.Collections;
using System.Linq;
using System.Text;
using string_short;
using jtext_EpicsClient;
using jtext_EpicsServer;
using EpicsJecket;
using EpicsJecketClient;
using System.Text.RegularExpressions;
using PSIEpics;
using System.Reflection;

namespace JtextEpicsInterface
{
    /// <summary>
    /// The JtextEpics device Object,That is a great design
    /// <para>With Device you can make many pv into one device,and device have device properties.you can access device by
    ///  DeviceName[DeviceProperty],and you can get deviceProperties,by only knowing the device name ,and device of the same tyoe have the same Properties</para>
    ///  <para>Also you can use EpicsJacket with device,and you can achieve more complex job by get the channel and EJClient</para>
    /// </summary>
    [Serializable]
    public class JEDevice
    {
        public const string  PREFIX_CMDFLAG_PV="DEVICECMDFLAG:";
        public const string PREFIX_CMD_PV = "CMD:";
        const string PREFIX = "PV:JEDEVICENAME:";
        const string JESERVERFIX = "DEVICEJESERVER:";

        #region cmd
        [NonSerialized]
        private object Parent; //server or client object we only recommend you use this to get values on client

        
        public delegate void CmdComesHandler(object val);
        [NonSerialized]
        CmdComesHandler myCmdComes;
        [NonSerialized]
        IDeviceSupport myDeviceSuport;

        [NonSerialized]
        JECLient JEClientCmd;   //used on server to monitort cmd

        Hashtable PvList;   //hold the DeviceProperty and the pv name
        Hashtable PropertyType; //this hold the data type of each DeviceProperty
        private bool isServer;  //if i am on a server or on a client
        private string MyName;  //the deviceName
        private string DevType;  //indicate the type of this device ,so you can lookup in the database 
        private string DevicePV;    //use this pv to get serialized device in pv sbyte[]
        #endregion

        #region EpicsJacket
        /// <summary>
        /// does this device has a epics jacket. 
        /// If so you can send message vis this device
        /// </summary>
        public bool HasEpicsJacket; //does this device has a epics jacket
        string EJServerName;
        string EJClientName;
        bool isbyte;
        int ackLev;
        /// <summary>
        /// this will initialized if you start EpicsJacketClient when this device is on client ,and has EpicsJacket
        /// <para>by using this EJClient you can have more control on the EpcsJacket like get CLientStatus,or recieve messages</para>
        /// </summary>
        [NonSerialized]
        public EJClient myEjClient;
        
        
        #endregion

        /// <summary>
        /// Gets the name of the device.
        /// </summary>
        /// <value>
        /// The name of the device.
        /// </value>
        public string DeviceName
        {
            get
            {
                return MyName;  
            }
        }

        /// <summary>
        /// Gets a value indicating whether this instance is on server.
        /// </summary>
        /// <value>
        /// 	<c>true</c> if this instance is on server; otherwise, <c>false</c>.
        /// </value>
        public bool isOnServer
        {
            get 
            {
                return isServer;    //if you are using this on server normally no
            }
        }

        /// <summary>
        /// Gets the type of the device.
        /// </summary>
        /// <value>
        /// The type of the device.
        /// </value>
        public string DeviceType
        {
            get
            {
                return DevType;
            }
        }




        /// <summary>
        /// Initializes a new instance of the <see cref="JEDevice"/> class.
        /// </summary>
        /// <param name="name">The Device name.</param>
        /// <param name="Device_type">The device_type.</param>
        /// <param name="OnServer">if set to <c>true</c> [on server].</param>
        /// <param name="ServerOrClient">The server or client object most case it's a server.note if you already have a JtextEpicsServer running in in this program assambly,youcan not create a new one,but if you not have any simply pass null,if will create one for you-in the case that is running in a EpicsJacket only IOC-</param>
        public JEDevice(string name,string Device_type,bool OnServer,object ServerOrClient)
        {
            MyName = name;
            DevicePV = PREFIX + name;
            DevType = Device_type;
            isServer = OnServer;
            PvList=new Hashtable();
            PropertyType = new Hashtable();
            if (ServerOrClient == null && OnServer==true)
            {
                Parent = (JEpicsServer)new JEpicsServer(JESERVERFIX + name, -1);     
                ((JEpicsServer)Parent).StartServer();
            }
            else
            {
                Parent = ServerOrClient;//when on server,if there is already a jeserver,then use it ,youcan not create 2 in one program
            }
            HasEpicsJacket = false;
        }


        #region ON Server
        /// <summary>
        /// Adds the device property.
        /// <para>populates the device,and Device Properties.A device property is like property to a class,you can use this access values with out knowing the pvname </para>
        /// <para>can be called only on server</para>
        /// </summary>
        /// <param name="Name">The Porperty Name.should be unique across the world like pvName</param>
        /// <param name="pvName">Name of the pv.this will be related with the device property in this device</param>
        /// <param name="DataType">Type of the data.<para>in this string ,we use a patern like: DataType;Direction.</para></param>
        public void addDeviceProperty(string Name, string pvName, string DataType)
        {
            if (isOnServer == false)
                return; //only server can add Device property
            PvList.Add(Name,pvName);
            PropertyType.Add(Name, DataType);        //in this string ,we use a patern like: DataType;Direction.
        }



        /// <summary>
        /// Publishes the device.
        /// <para>After you have populate the device call this to make the device visible across the network,and affter that you cannot change this device</para>
        ///  <para>can be called only on server</para>
        /// </summary>
        public void PublishDevice()     //make the device visible 
        {
            if (isOnServer == false)
                return; //only server can publish a Device
            MemoryStream TMemStm = new MemoryStream();
            BinaryFormatter TbinFmt = new BinaryFormatter();
            TbinFmt.Serialize(TMemStm, this);
            byte[] Tbytes = TMemStm.ToArray();
            sbyte[] TSbytes = Str_Short.ByteToSByte(Tbytes);
            Record_prop TrecorProp=new Record_prop();
            TrecorProp.ArrayLen=TSbytes.Length+100;
            TrecorProp.pvName=DevicePV;
            TrecorProp.DataClass=1;
            TrecorProp.DataType = CommonConst.DT_SBYTE;
            TrecorProp.Drv_name="NULL";
            TrecorProp.Drv_path="NULL";
            TrecorProp.isInput=true;
            ((JEpicsServer)Parent).AddRecord<sbyte>(TrecorProp);
            JEpicsArray<sbyte> tRecord = ((JEpicsArray<sbyte>)((JEpicsServer)Parent).getRecord(DevicePV));
            tRecord.PVAL = TSbytes; //set the serialized device to the pv
            TMemStm.Close();
            IniCmd();
            
        }

        /// <summary>
        /// Disposes the device.
        /// </summary>
        public void DisposeDevice()
        {
            ((JEpicsServer)Parent).DisposeRecord<sbyte>(DevicePV) ;
        }
        #endregion


        #region on client

        /// <summary>
        /// Retrieves the device.
        /// <para>Retrive the Device of the Given name,so you can use this device on the client</para>
        /// </summary>
        /// <param name="Name">The device name.</param>
        /// <returns>returns the device</returns>
        static public JEDevice  RetrieveDevice(string Name)    //get the device back and deserialize
        {
            JECLient client = new JECLient();
            try
            {

                string NamePV = PREFIX + Name;
                //JEDevice TDevice;
                client.AddChannel(NamePV);
                byte[] tByte = client.GetByte(NamePV);
                //byte[] tByte = Str_Short.SByteToByte(tSbytes);
                MemoryStream TMemStm = new MemoryStream(tByte);
                BinaryFormatter TbinFmt = new BinaryFormatter();
                object tObject = TbinFmt.Deserialize(TMemStm);
                client.DisposeAll();
                return (JEDevice)tObject;
            }
            catch
            {
                throw new SystemException("Can not Connect to the Device !!");
            }
        }


        /// <summary>
        /// Gets all property.usually called on client but on server it also works
        /// </summary>
        /// <returns>a string[] contains all the Device properties of this Device</returns>
        public string[] GetAllProperty()
        {
            ArrayList TArray=new ArrayList();
            foreach (string TProp in PvList.Keys)
            {
                TArray.Add(TProp);
            }
            return ((string[])(TArray.ToArray(typeof(string))));

        }

        /// <summary>
        /// Gets the PvName of the given device property in this device. 
        /// So you can use this PvName to get the channels,so you can do mo complicated things like create monitor
        /// </summary>
        /// <param name="DevicePropteryName">Name of the device proptery.</param>
        /// <returns>the PvName</returns>
        public string GetPvName(string DevicePropteryName)
        {
            return (string)PvList[DevicePropteryName];

        }


        /// <summary>
        /// Gets the Data type of the device property.
        /// </summary>
        /// <param name="DevicePropteryName">Name of the device proptery.</param>
        /// <returns>Data Type<seealso cref="CommonConst"/></returns>
        public string GetDataType(string DevicePropteryName)
        {
            string[] tStr = Regex.Split((string)PropertyType[DevicePropteryName],";",RegexOptions.IgnoreCase);  //in this string ,we use a patern like: DataType;Direction.
            return  tStr[0];
        }

        /// <summary>
        /// Gets the direction of the Device property -input or out put-.
        /// </summary>
        /// <param name="DevicePropteryName">Name of the device proptery.</param>
        /// <returns>the direction <seealso cref="ComminConst"/></returns>
        public string GetDirection(string DevicePropteryName)   //if it's input or out put
        {
            string[] tStr = Regex.Split((string)PropertyType[DevicePropteryName], ";", RegexOptions.IgnoreCase);

            return tStr[1];
        }



        /// <summary>
        /// Sets the client.
        /// <para>why set the client?
        ///   course the device can not work properly right after Retrieve you have to start the client object to make if work</para>
        /// </summary>
        public void  setClient() //the device can not work properly right after deSerialized you have to set the client object
        {

            isServer = false;   //when get from the pv it remain the same as it is on the server
            Parent = new JECLient();    //so  you have to set it to work on the client

            //and you shoul create channel for these PV in Device Properties
            //to same time when refer to this pvs
            string [] tProtery=this.GetAllProperty();
            try
            {
                foreach (string tProp in tProtery)
                {
                    if (this.GetDataType(tProp) == CommonConst.DT_BYTEARRAY || this.GetDataType(tProp) == CommonConst.DT_SBYTEARRAY)
                    {
                        ((JECLient)Parent).AddChannel(this.GetPvName(tProp));   //<ExtTimeType<string>> is not suitible fot array data
                    }
                    else
                    {
                        ((JECLient)Parent).AddChannel<ExtTimeType<string>>(this.GetPvName(tProp));   //get pv name for each Device Property
                    }
                }
            }
            catch
            {
                throw new SystemException("Can not Connect to the Device !!");
            }
            IniCmd();
            
        }

        /// <summary>
        /// Gets or sets the DeviceProperty Values with the specified device property.
        ///     you don't even have to use the epicsChannel to do this the device handle that for you,
        ///     be aware of the data type it may caurse some error
        /// </summary>
        public object this[string DeviceProperty]
        {
            get
            {
                if (isServer == true)
                {
                    JEpicsServer tServer = (JEpicsServer)Parent;
                    return tServer[(string)(PvList[DeviceProperty])].PVAL;  //on server side no string support
                }
                    
                JECLient tCLient = (JECLient)Parent;
                if (this.GetDataType(DeviceProperty) == CommonConst.DT_STRING)
                {
                   return tCLient.GetString((string)(PvList[DeviceProperty]));    //if it is aa string
                }
                else
                {
                    return tCLient.RecordVAL[(string)(PvList[DeviceProperty])];
                }
                
            }
            set
            {
                if (this.GetDirection(DeviceProperty) != CommonConst.DR_OUTPUT)   //the direction is not output ,thenyou can not change
                    return;
                if (isServer == true)
                {
                    JEpicsServer tServer = (JEpicsServer)Parent;
                    string tPVname = (string)(PvList[DeviceProperty]);
                    if (tServer[tPVname].RecordProperty.DataClass == 0)
                    {

                        switch (tServer[tPVname].RecordProperty.DataType)
                        {

                            case CommonConst.DT_DOUBLE:
                                {
                                    tServer[tPVname].PVAL = (double)value;
                                    break;
                                }
                            case CommonConst.DT_INT:
                                {
                                    tServer[tPVname].PVAL = (int)value;
                                    break;
                                }
                            case CommonConst.DT_SBYTE:
                                {
                                    tServer[tPVname].PVAL = (sbyte)value;
                                    break;
                                }
                            case CommonConst.DT_INT16:
                                {
                                    tServer[tPVname].PVAL = (Int16)value;
                                    break;
                                }
                            case CommonConst.DT_INT64:
                                {
                                    tServer[tPVname].PVAL = (Int64)value;
                                    break;
                                }
                            default:
                                {
                                    tServer[tPVname].PVAL = (double)value;
                                    break;
                                }
                        }
                        return;
                    }
                    else
                    {
                        switch (tServer[tPVname].RecordProperty.DataType)
                        {
                            case CommonConst.DT_DOUBLE:
                                {
                                    tServer[tPVname].PVAL = (double[])value;
                                    break;
                                }
                            case CommonConst.DT_INT:
                                {
                                    tServer[tPVname].PVAL = (int[])value;
                                    break;
                                }
                            case CommonConst.DT_SBYTE:
                                {
                                    tServer[tPVname].PVAL = (sbyte[])value;
                                    break;
                                }
                            case CommonConst.DT_INT16:
                                {
                                    tServer[tPVname].PVAL = (Int16[])value;
                                    break;
                                }
                            case CommonConst.DT_INT64:
                                {
                                    tServer[tPVname].PVAL = (Int64[])value;
                                    break;
                                }
                            default:
                                {
                                    tServer[tPVname].PVAL = (double[])value;
                                    break;
                                }
                        }
                        return;
                    }
                }
                //string[] tStr = Regex.Split((string)PropertyType[DeviceProperty], ";", RegexOptions.IgnoreCase);


                JECLient tCLient = (JECLient)Parent;
                if (this.GetDataType(DeviceProperty) == CommonConst.DT_STRING)
                {
                    tCLient.SetString((string)(PvList[DeviceProperty]),(string)value);    //if it is aa string

                }
                else
                {
                    tCLient.RecordVAL[(string)(PvList[DeviceProperty])] = value;
                }
                
            }

        }

        /// <summary>
        /// Gets the Epics channel of the given Device Property.
        /// </summary>
        /// <param name="DeviceProperty">The device property.</param>
        /// <returns>the epics channel for more complicated use</returns>
        public EpicsChannel getChannel(string DeviceProperty)
        {
            JECLient tCLient = (JECLient)Parent;
            return tCLient[(string)(PvList[DeviceProperty])];
        }




        #endregion


        #region on EJserver
        /// <summary>
        /// Sets the ejserver.
        /// <para>If you have a EpicsJakect to embed into this device use this to set it.after this the HasEpicsJacket will== true</para>
        /// </summary>
        /// <param name="ServerName">Name of the EJserver.</param>
        /// <param name="ISbyte">if set to <c>true</c> the EJServer uses byte message</param>
        public void setEjserver(string ServerName, bool ISbyte)
        {
            EJServerName = ServerName;
            isbyte = ISbyte;
            HasEpicsJacket = true;
        }
        #endregion

        #region onEjClient


        /// <summary>
        /// Starts the EJClient.
        /// <para>Onece you retrieve the device and set the client ,the device is hot,but you can not ues the EJClient,course you 
        ///  have not set and start your EJClient,give it a name and start it ,then you can use this device to send message</para>
        /// </summary>
        /// <param name="clientName">Name of the client.You dont have to specify the EJServer name couse the server info is already in this server,it will automaticly connect </param>
        /// <param name="ackLevel">The ack level.<seealso cref="EJClient"/></param>
        public void StartEjClient(string clientName, int ackLevel)
        {
            if (HasEpicsJacket == false)
            {
                return; //WTF!? youdont have a epicsjacket?
            }
            EJClientName = clientName;
            ackLev = ackLevel;
            myEjClient = new EJClient(EJServerName, EJClientName, isbyte, ackLev);  //fine i do all the job including create a client for you
            myEjClient.StartClient();
        }

        /// <summary>
        /// Disposes the EJCLient.
        /// </summary>
        public void DisposeEJ()
        {
            myEjClient.DisposeServer();
        }

        /// <summary>
        /// Send message to this device.
        /// </summary>
        /// <param name="MSG">The Message  byte[].</param>
        /// <returns>0 is ok</returns>
        public int Msg_send(byte[] MSG)
        {
            if (HasEpicsJacket == false)
            {
                return -2;
            }
            int st;
            st = myEjClient.Msg_send(MSG);
            return st;
        }

        /// <summary>
        /// Send message to this device.
        /// </summary>
        /// <param name="MSG">The message string.</param>
        /// <returns>0 is ok</returns>
        public int Msg_send(string MSG)
        {
            if (HasEpicsJacket == false)
            {
                return -2;
            }
            int st;
            st = myEjClient.Msg_send(MSG);
            return st;
        }



        #endregion

        #region command


        /// <summary>
        /// Loads the device support...
        /// Path is the dll file nanme
        /// </summary>
        /// <param name="path">The path.</param>
        public void LoadDeviceSupport(string path)
        {

            Assembly DrvAsm = Assembly.LoadFile(path);   //extract the assembly ftom the file
            Type[] DrvTypes = DrvAsm.GetTypes();   //get the types in this assembly
            foreach (Type DrvType in DrvTypes)
            {
                if (IsDeviceSupport(DrvType) == true)
                {
                    myDeviceSuport = ((IDeviceSupport)DrvAsm.CreateInstance(DrvType.FullName));  //create driver instace
                }
            }
        }

        private bool IsDeviceSupport(Type TDrv)
        {
            //return the Tdriv has the IJEDriver interface
            Type[] interfaces = TDrv.GetInterfaces();
            foreach (Type theInterface in interfaces)
            {
                if (theInterface.FullName == "JtextEpicsInterface.IDeviceSupport")
                {
                    return true;
                }
            }
            return false;
        }
        

        public void CmdArrived(EpicsChannel sender, object newValue )
        {
            Console.WriteLine("CMD Flag Changed");
            myCmdComes.BeginInvoke(newValue, null, null);

        }

        private void DeviceDoCmd(object newValue)
        {
            
            ExtTimeType<string> Trecod;
            Trecod = (ExtTimeType<string>)newValue;
            string flagVal = Trecod.Value.ToString();
            int tValue = 0;
            JEClientCmd.RecordVAL[PREFIX_CMDFLAG_PV + MyName] = tValue;
            
            if (flagVal == "1" )//&& myDeviceSuport!=null
            {
                string StrCmd = JEClientCmd.GetString(PREFIX_CMD_PV + MyName);
                myDeviceSuport.RunCmd(StrCmd, this);
                //Console.WriteLine("Doing : " + StrCmd);
            }
            
        }

        internal void IniCmd()
        {
            if (isServer == true)
            {
                //if onserver you have to create a client for it to monitor and get/set flag and cmds
                //and you have to use the parent server of tihs device to greate record for these
                JEClientCmd = new JECLient();
                
                //ini record here
                JEpicsServer tServer = (JEpicsServer)Parent;
                Record_prop TrecorProp=new Record_prop();
                //TrecorProp.ArrayLen = 128;
                TrecorProp.pvName = PREFIX_CMDFLAG_PV + MyName;
                TrecorProp.DataClass = 0;
                TrecorProp.Drv_name = "NULL";
                TrecorProp.Drv_path = "NULL";
                TrecorProp.DataType=CommonConst.DT_INT;
                TrecorProp.isInput = false;
                tServer.AddRecord(TrecorProp);
                
                Record_prop TrecorProp2=new Record_prop() ;
                TrecorProp2.ArrayLen = 128;
                TrecorProp2.pvName = PREFIX_CMD_PV + MyName;
                TrecorProp2.DataClass = 1;
                TrecorProp2.Drv_name = "NULL";
                TrecorProp2.Drv_path = "NULL";
                TrecorProp2.DataType = CommonConst.DT_SBYTE;
                TrecorProp2.isInput = false;
                tServer.AddRecord(TrecorProp2);


                JEClientCmd.AddChannel<ExtTimeType<string>>(PREFIX_CMDFLAG_PV + MyName);
                JEClientCmd.AddChannel(PREFIX_CMD_PV + MyName);
                JEClientCmd[PREFIX_CMDFLAG_PV + MyName].MonitorMask = MonitorMask.ALL;
                myCmdComes = new CmdComesHandler(DeviceDoCmd);
                ((EpicsChannel<ExtTimeType<string>>)JEClientCmd[PREFIX_CMDFLAG_PV + MyName]).MonitorChanged += new EpicsDelegate<ExtTimeType<string>>(CmdArrived);

                
            }
            else
            {
                JEClientCmd = (JECLient)Parent;
                JEClientCmd.AddChannel<ExtTimeType<string>>(PREFIX_CMDFLAG_PV + MyName);
                JEClientCmd.AddChannel(PREFIX_CMD_PV + MyName);
            }

            


        }

        /// <summary>
        /// Runs the commond.
        /// </summary>
        /// <param name="StrCmd">the command string of the commond.</param>
        public void RunCmd(string StrCmd)
        {
            if (JEClientCmd == null)
            {
                return;
            }
            JEClientCmd.SetString(PREFIX_CMD_PV+MyName,StrCmd);
            JEClientCmd.RecordVAL[PREFIX_CMDFLAG_PV + MyName] = (int)1;
        }


        #endregion







    }

    //-----------------IDevice support-------------------------------------------------

    public interface IDeviceSupport
    {
        string DeviceTypeName { get; }
        void RunCmd(string Cmd,JEDevice Device);

    }

    //----------------------------------------------New JEDevice----------------------------------------------
    //will suppor device proxy and stronly tyoed device
    /// <summary>
    /// Since the old JEDevice works fine, but supporting strongly typed device is a liitte pain.
    /// the device proxy is running on client side only, it wrapes up the jedevice for client use.
    /// </summary>
    public class JEDeviceProxy
    {
        //the device thate is retived
        public JEDevice myDevice;


        /// <summary>
        /// Loads the strongly typed proxy.
        /// will load the strongly typed assamibly to the classs static field
        /// </summary>
        /// <param name="_path">The _path.</param>
        public static void LoadStronglyTypedProxy(String _path)
        {
            //both assambily and type should be persitst
        }

        /// <summary>
        /// Determines whether [is strongly typed proxy loaded] [the specified _type name].
        /// </summary>
        /// <param name="_tyoeName">Name of the _type.</param>
        /// <returns>
        ///   <c>true</c> if [is strongly typed proxy loaded] [the specified _tyoe name]; otherwise, <c>false</c>.
        /// </returns>
        public static bool IsStronglyTypedProxyLoaded(string _typeName)
        {
            return false;
        }

        /// <summary>
        /// Gets the strongyl typed proxy.
        /// </summary>
        /// <param name="_device">The _device.</param>
        /// <returns></returns>
        public static JEDeviceProxy GetStrongylTypedProxy(JEDevice _device)
        {
            //create instance with assambily here
            return null;
        }

        /// <summary>
        /// Initializes a new instance of the <see cref="JEDeviceProxy"/> class.
        /// it is a internal method since only the static ReiveDevice will call it
        /// </summary>
        /// <param name="_device">The _device.</param>
        internal JEDeviceProxy(JEDevice _device)
        {
            myDevice = _device;
        }
        
        /// <summary>
        /// Retrieves the device proxy. 
        /// the old device retrive is used. but the device is put in a proxy object.
        ///   Also in this method it will return a strongly typed device if the strongly typed device support is loaded.
        /// </summary>
        /// <param name="Name">The name.</param>
        /// <returns></returns>
        static public JEDeviceProxy RetrieveDevice(string Name)    
        {
            JEDevice _myDevice= JEDevice.RetrieveDevice(Name);
            if (IsStronglyTypedProxyLoaded(_myDevice.DeviceType))
            {
                return GetStrongylTypedProxy(_myDevice);
            }
            else
            {
                return new JEDeviceProxy(_myDevice);
            }
            
        }


        /// <summary>
        /// Gets all property.usually called on client but on server it also works
        /// </summary>
        /// <returns>a string[] contains all the Device properties of this Device</returns>
        public string[] GetAllProperty()
        {
            return (myDevice.GetAllProperty());
        }

        /// <summary>
        /// Gets the PvName of the given device property in this device. 
        /// So you can use this PvName to get the channels,so you can do mo complicated things like create monitor
        /// </summary>
        /// <param name="DevicePropteryName">Name of the device proptery.</param>
        /// <returns>the PvName</returns>
        public string GetPvName(string DevicePropteryName)
        {
            return myDevice.GetPvName(DevicePropteryName);

        }


        /// <summary>
        /// Gets the Data type of the device property.
        /// </summary>
        /// <param name="DevicePropteryName">Name of the device proptery.</param>
        /// <returns>Data Type<seealso cref="CommonConst"/></returns>
        public string GetDataType(string DevicePropteryName)
        {
            return myDevice.GetDataType(DevicePropteryName);
        }

        /// <summary>
        /// Gets the direction of the Device property -input or out put-.
        /// </summary>
        /// <param name="DevicePropteryName">Name of the device proptery.</param>
        /// <returns>the direction <seealso cref="ComminConst"/></returns>
        public string GetDirection(string DevicePropteryName)   //if it's input or out put
        {
            return myDevice.GetDirection(DevicePropteryName);
        }



        /// <summary>
        /// Sets the client.
        /// <para>why set the client?
        ///   course the device can not work properly right after Retrieve you have to start the client object to make if work</para>
        /// </summary>
        public void setClient() //the device can not work properly right after deSerialized you have to set the client object
        {
            myDevice.setClient();
            myDevice.IniCmd();
        }

        /// <summary>
        /// Gets or sets the DeviceProperty Values with the specified device property.
        ///     you don't even have to use the epicsChannel to do this the device handle that for you,
        ///     be aware of the data type it may caurse some error
        /// </summary>
        public object this[string deviceProperty]
        {
            get
            {
                return myDevice[deviceProperty];

            }
            set
            {
                myDevice[deviceProperty] = value;
            }

        }

        /// <summary>
        /// Gets the Epics channel of the given Device Property.
        /// </summary>
        /// <param name="DeviceProperty">The device property.</param>
        /// <returns>the epics channel for more complicated use</returns>
        public EpicsChannel getChannel(string DeviceProperty)
        {
           return myDevice.getChannel(DeviceProperty);
        }

    }

}
